package newcrunch.grader;

import java.awt.CardLayout;
import java.awt.Point;
import java.awt.event.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingWorker;
import newcrunch.gui.RightPanel;
import newcrunch.util.DisplayHelper;
import newcrunch.util.Logging;
import newcrunch.util.Misc;

/**
 *
 * @author ccadm
 */
public class AuthManager 
{
    private LoginPanel loginPanel;
    private GradingPanel gradingPanel;
    private SelectionPanel selectionPanel;
    private RightPanel rightPanel;
    
    private LoginWorker loginWorker;
    
    private ConnectionManager connectionManager;
    
    public void setLoginPanel(LoginPanel panel)
    {
        loginPanel = panel;
        
        loginPanel.getLoginButton().addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                performLogin();                
            }
        });
        
        loginPanel.getPasswordField().addKeyListener(new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_ENTER)
                    performLogin();
            }
        });
    }
    
    public void setSelectionPanel(SelectionPanel panel)
    {
        selectionPanel = panel;
        
        selectionPanel.getTaskCombo().addItemListener(new ItemListener(){
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (selectionPanel.getCourseCombo().getSelectedIndex() >= 0 && 
                        selectionPanel.getTaskCombo().getSelectedIndex() >= 0)
                {
                    new SwingWorker<Object, Void>() {
                        @Override
                        protected Object doInBackground() throws Exception {
                            selectionPanel.getLoadingProgress().setVisible(true);
                            listUsers();
                            loadTestData(connectionManager, selectionPanel.getTaskCombo().getSelectedItem().toString());
                            selectionPanel.getLoadingProgress().setVisible(false);
                            return null;
                        }
                    }.execute();
                }
            }
        });
        
        selectionPanel.getCourseCombo().addItemListener(new java.awt.event.ItemListener() {
            @Override
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                updateGroups();
            }
        });
        
        selectionPanel.getGroupCombo().addItemListener(new java.awt.event.ItemListener() {
            @Override
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                updateTasks();
            }
        });
        
        selectionPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                if (evt.getButton() == MouseEvent.BUTTON3)
                {
                    Point point = selectionPanel.getMousePosition();
                    selectionPanel.getPopupMenu().show(selectionPanel, point.x, point.y);
                }
                else
                    selectionPanel.getPopupMenu().setVisible(false);
        }});
        
        selectionPanel.getSignOutMenuItem().addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                Misc.getBaseGUI(loginPanel).reset();
            }
        });
    }    
    
    public void setGradingPanel(GradingPanel panel)
    {
        gradingPanel = panel;
    }
    
    public void setRightPanel(RightPanel panel)
    {
        rightPanel = panel;
    }
    
    public ConnectionManager getConnectionManager()
    {
        return connectionManager;
    }
    
    class LoginWorker extends SwingWorker
    {
        @Override
        protected Object doInBackground() {
            loginPanel.getLoaderDisplay().setVisible(true);
            
            try {
                connectionManager = ConnectionManager.getConnection(loginPanel.getUsernameField().getText(), 
                        String.copyValueOf(loginPanel.getPasswordField().getPassword()));
                
                if (connectionManager != null)
                    listCoursesAndTasks();
                else
                    DisplayHelper.showErrorFrame(loginPanel, "Login Error", "Invalid username / password.");
            }
            catch (UnsupportedEncodingException ex) {
                Logging.log(ex);
            }
            catch (IOException ex) {
                Logging.log(ex);
                DisplayHelper.showErrorFrame(loginPanel, "Connection Error", "Unable to connect to server.");
            } catch (IllegalArgumentException e) {
                Logging.log(e);
                DisplayHelper.showErrorFrame(loginPanel, "Access Error", e.getMessage());
            }
            
            loginPanel.getLoaderDisplay().setVisible(false);
            return null;
        }
    }
    
    private void performLogin()
    {
        if (loginWorker == null || loginWorker.isDone())
        {
            loginWorker = new LoginWorker();
            loginWorker.execute();
        }
    }
    
    private void listCoursesAndTasks()
    {
        java.awt.Container container = loginPanel.getParent();
        updateCourses();
        CardLayout layout = (CardLayout)container.getLayout();
        layout.show(container, "selectionDisplay");
    }
    
    private void updateCourses()
    {
        try {
            if (connectionManager != null)
            {
                selectionPanel.getCourseCombo().setModel(new DefaultComboBoxModel(connectionManager.getCourses().toArray()));
                selectionPanel.getCourseCombo().setSelectedIndex(-1);
            }
        } catch (UnsupportedEncodingException e) {
            Logging.log(e);
        } catch (IOException e) {
            Logging.log(e);
            DisplayHelper.showErrorFrame(loginPanel, "Connection Error", "Unable to connect to server.");
        }
    }
    
    private void updateGroups()
    {
        try {
            if (selectionPanel.getCourseCombo().getSelectedIndex() >= 0)
            {
                String course = (String)selectionPanel.getCourseCombo().getSelectedItem();
                DefaultComboBoxModel model = new DefaultComboBoxModel(connectionManager.getGroups(course).toArray());
                selectionPanel.getGroupCombo().setModel(model);
                if (model.getSize() == 1) {
                    selectionPanel.getGroupCombo().setSelectedIndex(0);
                    updateTasks();
                }
                else {
                    selectionPanel.getGroupCombo().setSelectedIndex(-1);
                }
                selectionPanel.getGroupCombo().repaint();
            }
        } catch (UnsupportedEncodingException e) {
            Logging.log(e);
        } catch (IOException e) {
            Logging.log(e);
            DisplayHelper.showErrorFrame(loginPanel, "Connection Error", "Unable to connect to server.");
        }        
    }
    
    private void updateTasks()
    {
        try {
            if (selectionPanel.getGroupCombo().getSelectedIndex() >= 0)
            {
                String course = (String)selectionPanel.getCourseCombo().getSelectedItem();
                selectionPanel.getTaskCombo().setModel(new DefaultComboBoxModel(connectionManager.getTasks(course).toArray()));
                selectionPanel.getTaskCombo().setSelectedIndex(-1);
                selectionPanel.getTaskCombo().repaint();
            }
        } catch (UnsupportedEncodingException e) {
            Logging.log(e);
        } catch (IOException e) {
            Logging.log(e);
            DisplayHelper.showErrorFrame(loginPanel, "Connection Error", "Unable to connect to server.");
        }
    }
    
    private void listUsers()
    {
        java.awt.Container container = selectionPanel.getParent();
        String course = (String)selectionPanel.getCourseCombo().getSelectedItem();
        String task = (String)selectionPanel.getTaskCombo().getSelectedItem();
        String group = (String)selectionPanel.getGroupCombo().getSelectedItem();
        gradingPanel.getSubmissionsManager().updateSubmissions(course, task, group);
        CardLayout layout = (CardLayout)container.getLayout();
        layout.show(container, "gradingDisplay");
        
        try {
            rightPanel.setMarkingScheme(connectionManager.getMarkingScheme(course, task));
        } catch (UnsupportedEncodingException e) {
            Logging.log(e);
        } catch (IOException e) {
            Logging.log(e);
            DisplayHelper.showErrorFrame(loginPanel, "Connection Error", "Unable to connect to server.");
        }
    }    
    
    private void loadTestData(ConnectionManager mgr, String task) throws UnsupportedEncodingException, IOException
    {
        List<String> inputData = mgr.getData("input", task);
        List<String> outputData = mgr.getData("output", task);
        rightPanel.setInputTestData(inputData);
        rightPanel.setOutputTestData(outputData);
    }
    
    public void reset()
    {
        connectionManager = null;
        
        loginWorker = null;
        loginPanel.getLoaderDisplay().setVisible(false);
        loginPanel.getUsernameField().setText("");
        loginPanel.getPasswordField().setText("");
        
        selectionPanel.getTaskCombo().setModel(new DefaultComboBoxModel());
        selectionPanel.getTaskCombo().setSelectedIndex(-1);
        selectionPanel.getCourseCombo().setModel(new DefaultComboBoxModel());
        selectionPanel.getCourseCombo().setSelectedIndex(-1);
        selectionPanel.getGroupCombo().setModel(new DefaultComboBoxModel());
        selectionPanel.getGroupCombo().setSelectedIndex(-1);
        selectionPanel.getLoadingBar().setVisible(false);
    }
}
